//
//  Copy.h
//  面试题
//
//  Created by Toj on 8/8/21.
//

#pragma mark - 问题
1. copy 关键字的作用?
2. copy 与 strong 的区别
3. copy, mutableCopy方法. 浅拷贝, 深拷贝
4. 什么情况下用copy
5. block为什么要用copy
6. copy的好处

#pragma mark - copy 关键字的作用?
*** 成员变量复制不会copy操作, copy操作在setter方法内进行的
1> 对 对象 进行copy操作, copy 后的对象是个不可以变的对象, 即使用可变类型接收 也是不可变对象
e.g.: 一个可变字符串赋值一个 copy修饰的属性接收(类型可变/ 不可变), 都会copy一个新的不可变对象赋值, *** 注意是copy出来的不可变对象

2> 如果重写一个copy修饰的属性setter 方法, 那么你在赋值的时候必须要copy操作, 否则跟strong没什么去别
// ***mrc
- (void)setCname:(NSString *)cname {
    if (cname != _cname) {
        [_cname release];
        // _cname = [cname retain];
        _cname = [cname copy];
        // copy 内部会对新对象retain操作
    }
    return _cname;
}

// ***arc
- (void)setCname:(NSString *)cname {
    // *** 如果这么写跟strong一个样子
    // _cname = cname;
    
    _cname = [cname copy];
}

3> 内存管理
obj类型  修饰类型       是否产生新对象    引用计数
不可变   copy               否         旧对象+1
不可变   mutableCopy        是         新对象+1, 旧对象不变
可变     copy               是         新对象+1, 旧对象不变
可变     mutableCopy        是         新对象+1, 旧对象不变

#pragma mark -  copy 与 strong 的区别
1> 都是修饰对象的关键字
1.1> copy 修饰的对象会对进行浅拷贝/ 深拷贝操作, 而strong 只是引用对象而已,
浅拷贝/ 深拷贝取决于对象的类型

1.2> 内存管理可以看 1.3
strong 会对对象+1 操作, 不会派生新对象


#pragma mark -  copy, mutableCopy. 浅拷贝, 深拷贝
1> 如果能调用copy/ mutableCopy,
必须准守这2个对应的协议 <NSCopying, NSMutableCopying>,
现有的NSMutableArray, NSMutableSet, NSMutableString, 都已经遵守协议实现对应方法
e.g.: NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>

// 自定义一个类去遵守实现
e.g.:
@interface Person : NSObject  <NSCopying, NSMutableCopying>
- (id)mutableCopyWithZone:(NSZone *)zone {
    return [self.class allocWithZone:zone];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

浅拷贝: 指针变量复制, 2个指针(新&旧)最终指向的地址都是一个
深拷贝: 地址   复制, 复制一个一样的地址, 修改互相扯不上关系. 但是地址内的对象是浅拷贝
e.g. 钉钉里多人编辑excel
浅拷贝: 相当于复制一个人, 2人看同一个电脑上的excel
深拷贝: 相当于复制一电脑, 2人看各自的电脑上的excel
但是他们看到的excel是同一个, 修改也是修改的同一个


#pragma mark - 什么情况下用copy
1. block, 在mrc下 block是在栈上的, 需要copy堆中保存, 否则执行完代码块就被释放掉了
2. 字符串使用copy 这样外接无法修改值, 赋值也是对新对象的一次copy(赋值的是个可变对象)

#pragma mark - block为什么要用copy
1. 在arc下只要你引用外部变量都会copy到堆上

#pragma mark - copy的好处
1. 保证内部对象的地址是一个不可变的
